#include "networkzingmewebsocket.h"
#include "network/networkconnectionrequest.h"
#include <websocket.h>

namespace Network {
namespace Zingme {

Websocket::Websocket(QObject *parent) :
    QThread(parent),
    m_disconnector(0),
    m_locker(1),
    m_activator(0),
    m_disconnected(false),
    m_websocket(NULL)
{

}

bool Websocket::connect(const QString &server, int port, const QVariant &params)
{
    if (isRunning())
        return false;
    QVariantMap map = params.toMap();
    QString resource;
    if (map.size() > 0) {
        for (QVariantMap::ConstIterator iterator = map.begin();
             iterator != map.end();
             iterator++) {
            if(resource.length() == 0)
                resource = QString("%1=%2").arg(iterator.key(), (*iterator).toString());
            else
                resource += QString("&%1=%2").arg(iterator.key(), (*iterator).toString());
        }
    }

    if (resource.length() > 0)
        resource = "/?" + resource;
    m_websocket = new Tufao::WebSocket(this);
    QObject::connect(m_websocket,
                     &Tufao::WebSocket::connected,
                     this,
                     &Websocket::onConnected);
    QObject::connect(m_websocket,
                     &Tufao::WebSocket::newMessage
                     , this,
                     &Websocket::received);
    QObject::connect(m_websocket,
                     &Tufao::WebSocket::disconnected,
                     this,
                     &Websocket::onDisconnected);
    Tufao::Headers headers;
    headers.insert("session", "abc");
    m_websocket->connectToHost(server, port, resource.toLatin1(), headers);

    m_server = server;
    m_port = port;
    m_params = params;
    m_disconnected = false;
    return true;
}

bool Websocket::send(ConnectionRequest *request)
{
    if (!isRunning())
        return false;
    m_locker.acquire();
    m_requests.append(request);
    m_locker.release();
    m_activator.release();
    return true;
}

void Websocket::disconnect()
{
    if (!isRunning())
        return;
    m_locker.acquire();
    m_disconnected = true;
    m_locker.release();

    m_activator.release();
    m_disconnector.acquire();
}

void Websocket::stop()
{
    if (!isRunning())
        return;
    m_locker.acquire();
    m_disconnected = true;
    m_locker.release();
    m_activator.release();
    m_disconnector.acquire();
}

void Websocket::run()
{
    do {
        m_activator.acquire();
        m_locker.acquire();
        if (m_disconnected) {
            m_locker.release();
            break;
        }
        if (m_requests.size() == 0) {
            m_locker.release();
            continue;
        }
        Network::ConnectionRequest *request = m_requests.first();
        m_requests.removeFirst();
        m_locker.release();
        QByteArray data = request->content();

        if (m_websocket->sendMessage(data) != true) {
            emit failed(request);
        } else {
            emit sended(request);
        }
    } while (true);
    m_disconnector.release();
}

void Websocket::onFinished()
{

}

void Websocket::onConnected()
{
    if (m_websocket == NULL)
        return;
    start();
    emit connected();
}

void Websocket::onReceived(QByteArray message)
{
    if (m_websocket == NULL)
        return;
    emit received(message);
}

void Websocket::onDisconnected()
{
    if (m_websocket == NULL)
        return;
    stop();
    delete m_websocket;
    m_websocket = NULL;
}

} // namespace zingme
} // namespace network
